--[[
	Copyright (C) Udorn (Blackhand)
--]]

yaka = yaka or {}

local version = 1
if (yaka.View and yaka.View.version >= version) then
	return 
end

yaka.View = {}
yaka.View.prototype = {}
yaka.View.metatable = {__index = yaka.View.prototype}

local YakaGui = LibStub("YakaGui", true)
local log = vendor.Debug:new("View")

local function _OnScript(this, script, ...)
	--log:Debug("_OnScript script [%s] viewType [%s]", script, this.view:GetViewType())
	local self = this.view
	local scripts = self.scripts[script]
	if (scripts) then
		self.scriptInfo.arg = self.cfg.arg
		for k,v in pairs(scripts) do
			v(self.scriptInfo, this, ...)
		end
	end
end

local function _OnUpdate(this, ...)
	_OnScript(this, "OnUpdate", ...)
end

local function _OnEnter(this, ...)
	_OnScript(this, "OnEnter", ...)
end

local function _OnLeave(this, ...)
	_OnScript(this, "OnLeave", ...)
end


local function _SetTooltip(self, tooltip)
	self.cfg.tooltip = tooltip
	if (tooltip and not self.tooltipScriptsAdded) then
		self.tooltipScriptsAdded = true
		self:AddScript("OnEnter", function(info, this)
			local tooltip = info.view.cfg.tooltip
			if (tooltip) then
	    		GameTooltip_SetDefaultAnchor(GameTooltip, this)
				GameTooltip:SetOwner(this, "ANCHOR_RIGHT") 
    			GameTooltip:SetText(tooltip, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1, true)
    			GameTooltip:Show()
			end
		end)
		self:AddScript("OnLeave", function(info)
			if (info.view.cfg.tooltip) then 
				GameTooltip:Hide()
			end
		end)
	end
end

local function _AddScript(scripts, func)
	for k,v in pairs(scripts) do
		if (v == func) then
			return
		end
	end
	tinsert(scripts, func)
end

--[[ 
	Creates a new instance.
--]]
--function yaka.View:new(cfg)
--	local instance = setmetatable({}, self.metatable)
--	
--	return instance
--end

function yaka.View.prototype:InitCfg(cfgIn)
	local cfg = {}
	
	cfg.name = cfgIn.name
	cfg.order = cfgIn.order
	cfg.viewType = cfgIn.viewType
	cfg.width = cfgIn.width or 400
	cfg.height = cfgIn.height or 400
    cfg.paddingLeft = cfgIn.paddingLeft or 0
    cfg.paddingRight = cfgIn.paddingRight or 0
    cfg.paddingTop = cfgIn.paddingTop or 0
    cfg.paddingBottom = cfgIn.paddingBottom or 0
    cfg.topLevel = cfgIn.topLevel
    cfg.frameStrata = cfgIn.frameStrata
   	cfg.onClick = cfgIn.onClick
	cfg.arg = cfgIn.arg
	cfg.testMode = cfgIn.testMode
	cfg.tooltip = cfgIn.tooltip
	cfg.id = cfgIn.id
	cfg.point = cfgIn.point
	cfg.relativePoint = cfgIn.relativePoint
	cfg.relative = cfgIn.relative
	cfg.left = cfgIn.left
	cfg.top = cfgIn.top
	cfg.background = cfgIn.background
	cfg.onUpdate = cfgIn.onUpdate
	cfg.horizontalAlign = cfgIn.horizontalAlign or "LEFT"
	 
    self.cfg = cfg
    self.scriptInfo = {view = self, arg = self.cfg.arg}
end

function yaka.View.prototype:InitFrame()
	
	local cfg = self.cfg
	local frame = self.frame
	
	frame.view = self
	frame:Hide()

	if ("string" ~= type(cfg.width)) then
		frame:SetWidth(cfg.width)
	end
	if ("string" ~= type(cfg.height)) then
		frame:SetHeight(cfg.height)
	end
	if (cfg.frameStrata) then
		frame:SetFrameStrata(cfg.frameStrata)
	end
	if (cfg.topLevel) then
		frame:SetToplevel(true)
	end
	
	if (cfg.testMode) then
		local texture = frame:CreateTexture()
		texture:SetAllPoints(frame)
		texture:SetTexture(1, 0, 0, 1)
	end
	
	if (cfg.background) then
		local texture = frame:CreateTexture()
		texture:SetAllPoints(frame)
		texture:SetTexture(cfg.background.file)
		if (cfg.background.texCoords) then
			texture:SetTexCoord(unpack(cfg.background.texCoords))
		end
		if (cfg.background.alpha) then
			texture:SetAlpha(alpha)
		end
		if (cfg.background.vertexColor) then
			texture:SetVertexColor(unpack(cfg.background.vertexColor))
		end
		
		self.backgroundTexture = texture
	end
	
	_SetTooltip(self, cfg.tooltip)

	if (cfg.point) then
		frame:SetPoint(cfg.point, cfg.relative or UIParent, cfg.relativePoint or cfg.point, cfg.left or 0, cfg.top or 0)
	end
	
	if (cfg.onUpdate) then
		self:AddScript("OnUpdate", cfg.onUpdate)
	end
	
	YakaGui:RegisterView(self)
end
	
--[[
	Shows the window if parameter visible is true. Otherwise it's hidden.
--]]
function yaka.View.prototype:SetVisibility(visible)
	if (visible) then
		self.frame:Show()
	else
		self.frame:Hide()
	end
end

function yaka.View.prototype:GetMeasuredWidth()
	return self.cfg.width
end

function yaka.View.prototype:GetMeasuredHeight()
	return self.cfg.height
end

--[[
	Returns paddingLeft, paddingRight, paddingTop, paddingBottom
--]]
function yaka.View.prototype:GetPadding()
	local cfg = self.cfg
	return cfg.paddingLeft, cfg.paddingRight, cfg.paddingTop, cfg.paddingBottom
end

function yaka.View.prototype:SetPadding(paddingLeft, paddingRight, paddingTop, paddingBottom)
	self.cfg.paddingLeft = paddingLeft or 0
	self.cfg.paddingRight = paddingRight or 0
	self.cfg.paddingTop = paddingTop or 0
	self.cfg.paddingBottom = paddingBottom or 0
end

function yaka.View.prototype:Width()
	return self.frame:GetWidth()
end

function yaka.View.prototype:GetHeight()
	return self.frame:GetHeight()
end

function yaka.View.prototype:SetWidth(width)
	self.cfg.width = width
end

function yaka.View.prototype:SetHeight(height)
    self.cfg.height = height
end

function yaka.View.prototype:Layout(x, y, width, height)
	--log:Debug("Layout x [%s] y [%s] width [%s] height [%s] cfgHeight [%s] type [%s]", x, y, width, height, self.cfg.height, self.cfg.viewType)
	self.frame:ClearAllPoints()
	self.frame:SetPoint("TOPLEFT", x, y)
	self.frame:SetWidth(width)
	if ("fit" ~= self.cfg.height) then
		self.frame:SetHeight(height or self.cfg.height)
	end
end

function yaka.View.prototype:GetViewType()
	return self.cfg.viewType
end

function yaka.View.prototype:SetOrder(order)
	self.cfg.order = order
end

function yaka.View.prototype:SetArg(arg)
	self.cfg.arg = arg
end

function yaka.View.prototype:SetTooltip(tooltip)
	_SetTooltip(self, tooltip)
end

function yaka.View.prototype:SetPoint(point, relativeView, relativePoint, x, y)
	if (IsFrameHandle(relativeView)) then
		self.frame:SetPoint(point, relativeView, relativePoint, x, y)
	else
		self.frame:SetPoint(point, relativeView.frame, relativePoint, x, y)
	end
end

function yaka.View.prototype:SetId(id)
	self.cfg.id = id
end

function yaka.View.prototype:GetId()
	return self.cfg.id
end

function yaka.View.prototype:GetName()
	return self.cfg.name
end

function yaka.View.prototype:Destroy()
	log:Debug("destroy self [%s] cfg [%s]", self, self.cfg)
	log:Debug("Destroy type [%s]", self:GetViewType())
	self:SetVisibility(false)
	YakaGui:UnregisterView(self)
end

function yaka.View.prototype:AddScript(script, func)
	log:Debug("AddScript")
	if (not self.scripts) then
		self.scripts = {}
	end
	
	local scripts = self.scripts[script]
	if (not scripts) then
		scripts = {}
		_AddScript(scripts, func)
		self.scripts[script] = scripts
		if (script == "OnEnter") then
			self.frame:SetScript(script, _OnEnter)
		elseif (script == "OnLeave") then
			self.frame:SetScript(script, _OnLeave)			
		elseif (script == "OnUpdate") then
			self.frame:SetScript(script, _OnUpdate)
		else
			error("unhandled script \""..script.."\"")
		end
	else
		_AddScript(scripts, func)
	end
end

function yaka.View.prototype:SetBackgroundVisibility(visible)
	if (self.backgroundTexture) then
		if (visible and not self.backgroundTexture:IsVisible()) then
			self.backgroundTexture:Show()
		elseif (not visible and self.backgroundTexture:IsVisible()) then
			self.backgroundTexture:Hide()
		end
	end
end

function yaka.View.prototype:GetHorizontalAlign()
	return self.cfg.horizontalAlign
end